%{
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int lines=1;//行数计数器
int keys=0;//关键词计数器
int numbers=0;//数字计数器
int identifiers=0;//标识符计数器
int operators=0;//算术操作符计数器
int relationals=0;//关系符计数器
int error_identifiers=0;//错误词项计数器
int  headfile_num=0;//头文件计数器
int  strings=0;//字符串计数器
int  characters=0;//字符计数器
int error_lines[10];//用于存放错误词项所在行数
%}
LB	    "{"
LP	    "("
RB	    "}"
RP	    ")"
PLUS	"+"
MINUS	"-"
MULT	"*"
DIV	    "/"
MOD	    "%"
PLUSA	"+="
MINUSA	"-="
MULA	"*="
DIVA	"/="
MODA	"%="
LS	    "<<"
RS	    ">>"
LSA	    "<<="
RSA	    ">>="
NOT	    "!"
BITAND	"&"
BITOR	"|"
XOR	    "^"
COMPL	"~"
AND		"&&"
OR		"||"
LT		"<"
LE		"<="
GT		">"
GE		">="
EQ		"=="
NE		"!="
ASSIGN	"="
DOT		"."
MS		"->"
LA		"["
RA		"]"
POSINC	"++"
POSDEC	"--"
PREINC	"++"
PREDEC	"--"
UNARYMINS	"-"
UNARYPLUS	"+"
DEREFERECE	"*"
ADDRESS	"&"
COMMA	","
SC		";"


ASM		"asm"
AUTO	"auto"
BOOL	"bool"
BREAK	"break"
CASE	"case"
CATCH	"catch"
CHAR	"char"
CLASS	"class"
CONST	"const"
C_CAST	"const_cast"
CONTINUE	"continue"
DEFAULT	"default"
DELETE	"delete"
DO		"do"
DOUBLE	"double"
ELSE	"else"
ENUM	"enum"
EXTERN	"extern"
FALSE	"false"
FLOAT	"float"
FOR		"for"
FRIEND	"friend"
GOTO	"goto"
IF		"if"	
INLINE	"inline"
INT		"int"
LOG		"log"
LONG	"long"
NAMESPACE	"namespace"
NEW		"new"
OPERATOR	"operator"
PRIVATE	"private"
PROTECTED	"protected"
PUBLIC	"public"
REGISTER	"register"
R_CAST	"reinterpret_cast"
RETURN	"return"
SHORT	"short"
SIGNED	"signed"
SIZEOF	"sizeof"
STATIC	"static"
S_CAST	"static_cast"
STRUCT	"struct"
SWITCH	"switch"
TEMPLATE	"template"
THIS	"this"
THROW	"throw"
TRUE	"true"
TRY		"try"
TYPEDEF	"typedef"
TYPEID	"typeid"
TYPENAME	"typename"
UNION	"union"
UNSIGNED	"unsigned"
USING	"using"
VIRTUAL	"virtual"
VOID	"void"
VOLATILE	"volatile"
WCHAR_T	"wchar_t"
WHILE	"while"
MAIN	"main"
DEFINE	"define"
INCLUDE	"include"
STRING  \"(.|\\t)+\"
CHARACTER \'(.|\\t)\'



DIGIT	[0-9]
LETTER	[a-zA-Z]
C_PLUS_OP	{DOT}|{MS}
RELATION	{LT}|{LE}|{GT}|{GE}|{EQ}|{NE}
LOGICAL	    {COMPL}|{NOT}|{BITAND}|{BITOR}|{AND}|{OR}
COMMENTS	"/*"(.|\n)*"*/"|"//".*
SEPARATPR	{COMMA}|{SC}|{LB}|{LP}|{RB}|{RP}
OPERATORS	{PLUS}|{MINUS}|{MULT}|{MOD}|{DIV}|{PLUSA}|{MINUSA}|{MULA}|{DIVA}|{MODA}|{LS}|{RS}|{LSA}|{RSA}|{POSINC}|{POSDEC}|{PREINC}|{PREDEC}|{ASSIGN}
FORMAT	    "%d"|"%lld"|"%f"|"%lf"|"%c"|"%x"|"%a"|"%e"|"%g"|"%o"
KEYWORDS	{AUTO}|{BOOL}|{BREAK}|{CASE}|{CATCH}|{CHAR}|{CLASS}|{CONST}|{C_CAST}|{CONTINUE}|{DEFAULT}|{DELETE}|{DO}|{DOUBLE}|{ELSE}|{ENUM}|{EXTERN}|{FALSE}|{FLOAT}|{FOR}|{FRIEND}|{GOTO}|{IF}|{INLINE}|{INT}|{LOG}|{LONG}|{NAMESPACE}|{NEW}|{OPERATOR}|{PRIVATE}|{PROTECTED}|{PUBLIC}|{REGISTER}|{RETURN}|{SHORT}|{SIGNED}|{SIZEOF}|{STATIC}|{STRUCT}|{SWITCH}|{TEMPLATE}|{THIS}|{TRUE}|{TRY}|{TYPEDEF}|{USING}|{VIRTUAL}|{UNION}|{VOID}|{WHILE}|{MAIN}
HEADFILE	"iostream"|"stdio.h"|"stdlib.h"|"string.h"|"math.h"|"memory.h"|"cstdio"|"cstring"|"algorithm"|"cmath"
ESC	        "\\a"|"\\b"|"\\f"|"\\n"|"\\r"|"\\t"|"\\v"|"\\'"

%%
[\n]								{ lines++; }
[ \t]
[#]{INCLUDE}[ ][<]{HEADFILE}[>]		{ fprintf(yyout,"Lines: %d   head file:---------%s\n", lines, yytext);headfile_num++; }
[#]{DEFINE}							{ fprintf(yyout,"Lines: %d   pretreatment:------%s\n", lines, yytext); }
{KEYWORDS}							{ fprintf(yyout,"Lines: %d   keywords:----------%s\n", lines, yytext); keys++; }
([-+]?{DIGIT}+)|([+-]?[0][0-7]+)|([+-]?[0][xX][0-9a-fA-F]+)	{ fprintf(yyout,"Lines: %d   integer------------%s\n", lines, yytext); numbers++; }
[-+]?{DIGIT}+(\.{DIGIT}+)([eE][+-]?{DIGIT}+)?			    { fprintf(yyout,"Lines: %d   real---------------%s\n", lines, yytext); numbers++; }
({LETTER}|[_])({LETTER}|{DIGIT}|[_])*				        { fprintf(yyout,"Lines: %d   identifier---------%s\n", lines, yytext); identifiers++; }
{STRING}							{ fprintf(yyout,"Lines: %d   string-------------%s\n", lines, yytext); strings++;}
{CHARACTER}							{ fprintf(yyout,"Lines: %d   characters---------%s\n", lines, yytext); characters++;}
{OPERATORS}							{ fprintf(yyout,"Lines: %d   operators----------%s\n", lines, yytext); operators++; }
{LOGICAL}							{ fprintf(yyout,"Lines: %d   logical------------%s\n", lines, yytext); }
{SEPARATPR}							{ fprintf(yyout,"Lines: %d   separatpr----------%s\n", lines, yytext); }
{FORMAT}							{ fprintf(yyout,"Lines: %d   format-------------%s\n", lines, yytext); }
{LA}								{ fprintf(yyout,"Lines: %d   Array_LA-----------%s\n", lines, yytext ); }
{RA}								{ fprintf(yyout,"Lines: %d   Array_RA-----------%s\n", lines, yytext ); }
[ \"]								{ fprintf(yyout,"Lines: %d   quotation mark-----%s\n", lines, yytext ); }
{ESC}								{ fprintf(yyout,"Lines: %d   Escape-------------%s\n", lines, yytext ); }
{RELATION}							{ fprintf(yyout,"Lines: %d   relope-------------%s\n", lines, yytext); relationals++; }
{C_PLUS_OP}							{ fprintf(yyout,"Lines: %d   c++operation-------%s\n", lines, yytext); relationals++; }
({DIGIT}+)({LETTER}+)				{ fprintf(yyout,"Lines: %d   error identifier---%s\n", lines, yytext);error_identifiers++;error_lines[error_identifiers-1]=lines;}
{COMMENTS}							{ fprintf(yyout,"Lines: %d   comments-----------%s\n", lines, yytext); }
%%
int main(int argc,char **argv)
{
	++argv, --argc; /* skip over program name */
	if ( argc > 0 )
	{
		yyin = fopen(argv[0], "r" );
		yyout = fopen("result.tok", "w");
		if(!yyout) printf("can`t open result.tok");
	}
	else
		yyin = stdin;
	if(yyin)
	{
		printf( "******************************************************************\n" );
		printf( "Filename:%s\n",argv[0]);
		yylex();
		if(error_identifiers>0)
		{
		printf( "******************************************************************\n" );//输出错误总数及所在行数
		printf( "%d errors \n", error_identifiers );
		int i;
		for(i=0;i<error_identifiers;i++)
		printf( "at line %d\n",error_lines[i]);
		}
		printf( "******************************************************************\n" );//输出各类词项总数
		printf( "Analyzed Results:\n");
		printf( "headfile_num=%d\n", headfile_num );
		printf( "lines=%d\n", lines-1 );
		printf( "keywords=d\n", keys );
		printf( "relationals=d\n", relationals );
		printf( "operators=%d\n", operators );
		printf( "numbers=%d\n", numbers );
		printf( "identifiers=%d\n", identifiers );
		printf( "strings=%d\n", strings );
		printf( "characters=%d\n", characters );
		fclose(yyin);
		fclose(yyout);
		printf( "******************************************************************\n" );
		system( "pause" );
	}
	else
		printf("Invalid Filename \n");
	return 0;
}

int yywrap()
{	
	return 1;
}